package collector.core.util;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import system.common.Constants;
import collector.core.CollectConstants;
import collector.core.TaskConstVO;
import collector.core.config.ConfigModule;
import collector.module.ModuleJob;
import collector.task.JobStateInfoData;
import collector.task.JobStateVO;
import collector.task.JobTaskVO;
import collector.task.JobTriggerVO;
import collector.task.JobVO;

/**
 * <pre>
 * Class : collector.util.JobTaskUtil / JobTaskUtil.java
 * 	Define Class Object : Quartz Job Task Schedule 관련 처리 Util Method 구현 
 * <br>
 * </pre>
 * 
 * @author ytjeong / apexcns,Inc.
 * @version 1.0
 * @see javadoc
 * @since 2012. 9. 12.
 */
public class JobTaskUtil {

	private static Logger _log = LoggerFactory.getLogger(JobTaskUtil.class);
	private static final String _LogPrefixStr = CollectConstants.LOGGER_MODULE_NAME_JTU
			+ CollectConstants.LOGGER_MODULE_NAME_AFTFIX;

	private static Map<String, JobStateVO> pjsVoMap = new HashMap<String, JobStateVO>();
	private static Map<String, JobStateVO> tjsVoMap = new TreeMap<String, JobStateVO>();

	/**
	 * <pre>
	 * Method : JobTaskUtil.getModuleJobState()
	 * 	Task Job 관련 VO 객체를 이용한 Job State를 생성한다.
	 * <br>
	 * @param cmd
	 * @return 
	 * type of void
	 * </pre>
	 */
	public static void getModuleJobState(String cmd) throws FileNotFoundException {
		File file = null;

		_log.info(_LogPrefixStr
				+ "----- loaing module job state -------------------");
		if ("Y".equals(cmd) || "N".equals(cmd)) {
			ConfigModule configModule = ConfigModule.getConfig(ConfigModule.class);

			for (TaskConstVO tcVo : configModule.getModuleTaskList()) {
				if (cmd.equals(tcVo.getUseYN())) {
					JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_PAST, "PAST");
					JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_CURRENT, "CURRENT");
					JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_NEXT, "NEXT");
				}
			}
		} else if ("".equals(cmd)) {
			ConfigModule configModule = ConfigModule.getConfig(ConfigModule.class);

			for (TaskConstVO tcVo : configModule.getModuleTaskList()) {
				JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_PAST, "PAST");
				JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_CURRENT, "CURRENT");
				JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_NEXT, "NEXT");
			}
		} else {
			TaskConstVO tcVo = ConfigModule.newInstance().getModuleTask(cmd);
			JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_PAST, "PAST");
			JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_CURRENT, "CURRENT");
			JobTaskUtil.getModuleJobStateLog(tcVo, "_" + CollectConstants.STATE_NEXT, "NEXT");
		}
		// TreeMap을 이용하여 정렬
		tjsVoMap.clear();
		tjsVoMap.putAll(pjsVoMap);
		FileUtil.directoryCheck(Constants.moduleJobStatePath);
		file = new File(Constants.moduleJobStatePath + "MODULE_JOB_STATE_Current.xml");
		net.apexcns.core.util.XmlBindUtil.toXmlWithNd(JobStateVO.class, tjsVoMap, file);
		// HashMap 초기화
		pjsVoMap.clear();
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.getModuleJobStateLog()
	 * 	Job State 관련 xml을 읽어 들여 지정한 hashmap에 저장한다.
	 * <br>
	 * @param tcVo
	 * @param path
	 * @param point
	 * @return 
	 * type of void
	 * </pre>
	 */
	public static void getModuleJobStateLog(TaskConstVO tcVo, String path, String point) throws FileNotFoundException {
		JobStateVO jsVo = null;
		File file = null;
		String fullPath = tcVo.getTaskPathState() + tcVo.getTaskName() + path;
		if (FileUtil.checkFile(fullPath)) {
			file = new File(fullPath);
			jsVo = net.apexcns.core.util.XmlBindUtil.fromXmlWithNd(JobStateVO.class, file);
			jsVo.setPoint(point);
			pjsVoMap.put(tcVo.getTaskName() + " :: " + point, jsVo);
		}
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobTask()
	 * 	Task Job 관련 VO 객체를 이용한 Job Task 생성
	 * <br>
	 * @param jobVo
	 * @param jobTriggerVo
	 * @return 
	 * type of JobTaskVO
	 * </pre>
	 */
	public static JobTaskVO generateJobTask(JobVO jobVo,
			JobTriggerVO jobTriggerVo) { /* 현재 미사용 */
		JobTaskVO jobTaskVo = new JobTaskVO();
		jobTaskVo = generateJobTask(jobVo.getJobName(), jobVo.getJobGroup(),
				jobVo.getJobClass(), jobTriggerVo.getTriggerName(),
				jobTriggerVo.getTriggerGroup(),
				jobTriggerVo.getScheduleStartTime(),
				jobTriggerVo.getDurationType(), jobTriggerVo.getDurationValue());

		return jobTaskVo;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobTask()
	 * 	 클래스 객체를 이용한 Job Task 생성
	 * 	generateJobTask(JobVO jobVo, JobTriggerVO jobTriggerVo)를 통해 호출됨
	 * <br>
	 * @param jobName
	 * @param jobGroup
	 * @param jobClass
	 * @param triggerName
	 * @param triggerGroup
	 * @param ScheduleStartTime
	 * @param durationType
	 * @param durationValue
	 * @return 
	 * type of JobTaskVO
	 * </pre>
	 */
	public static JobTaskVO generateJobTask(String jobName, String jobGroup,
			Class<? extends Job> jobClass, String triggerName,
			String triggerGroup, String ScheduleStartTime, String durationType,
			int durationValue) {
		JobTaskVO jobTaskVo = new JobTaskVO();
		// 작업 ID Setting
		jobTaskVo.setJobIDs(jobName);
		// jobKey 생성
		JobKey jobKey = generateJobKey(jobName, jobGroup);
		jobTaskVo.setJobKey(jobKey);
		_log.debug(_LogPrefixStr + " JobKey=" + jobKey);
		// jobDetail 생성
		JobDetail job = generateJobDetail(jobKey, jobClass);
		jobTaskVo.setJob(job);
		// JobDetail job = generateJobDetail(jobKey, jobClass);
		// jobTaskVo.setJob(job);
		_log.debug(_LogPrefixStr + " JobDetail=" + job);
		// JobTriggerVO 생성
		JobTriggerVO jobTriggerVo = new JobTriggerVO(triggerName, triggerGroup,
				ScheduleStartTime, durationType, durationValue); // ScheduleStartTime[=HHmmss]
		_log.debug(_LogPrefixStr + " JobTrigger=" + jobTriggerVo);

		// Trigger 생성
		SimpleTrigger trigger = generateTrigger(jobTriggerVo);
		jobTaskVo.setTrigger(trigger);

		return jobTaskVo;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobTask()
	 * 	클래스 객체의 문자열을 이용한 Job Task 생성
	 * <br>
	 * 	return type of JobTaskVO
	 * <br>
	 * @param jobName
	 * @param jobGroup
	 * @param jobClassStr
	 * @param triggerName
	 * @param triggerGroup
	 * @param ScheduleStartTime
	 * @param durationType
	 * @param durationValue
	 * @return
	 * @throws ClassNotFoundException
	 * </pre>
	 */
	@SuppressWarnings("unchecked")
	public static JobTaskVO generateJobTask(String jobName, String jobGroup,
			String jobClassStr, String triggerName, String triggerGroup,
			String ScheduleStartTime, String durationType, int durationValue)
			throws ClassNotFoundException {

		// 새로이 JobTaskVO를 생성하고 초기값을 세팅한 후 리턴한다.
		JobTaskVO jobTaskVo = new JobTaskVO();

		String deaultClass = CollectConstants.DEFAULT_TASK_CLASSSTR;

		Class<? extends Job> jobClass = null; // Auto Generate jobClass
		try {// 지정된 Task 클래스를 정의
				// Job Class Name is jobTaskName + "_Job"
			jobClass = (Class<? extends Job>) Class.forName(jobClassStr);
		} catch (ClassNotFoundException e) {
			_log.warn(_LogPrefixStr
					+ " retry Default Definition for Job Module Class :: "
					+ e.getMessage() + " to " + deaultClass);
			try {// Task Job 클래스가 없는 경우 default Task Job 클래스를 정의,
					// default Job Class Name is JobClassName
				jobClass = (Class<? extends Job>) Class.forName(deaultClass);

			} catch (ClassNotFoundException e1) {
				// TODO::default Task Job 클래스도 없는 경우 처리 방안 (Scheduler 예외발생?)
				_log.error(
						_LogPrefixStr
								+ " Fail Default Definition for Job Class :: "
								+ e1.getMessage(), e1);
				throw e1;
			}
		}

		// FIXME::remove Check
		if (jobClass == ModuleJob.class)
			_log.debug(_LogPrefixStr
					+ "Class Object equals Define Class 1............");
		if (jobClass.getName().equals("ModuleJob"))
			_log.debug(_LogPrefixStr
					+ "Class Object equals Define Class 2............");

		// 작업 ID Setting
		jobTaskVo.setJobIDs(jobName);
		// jobKey 생성
		JobKey jobKey = generateJobKey(jobName, jobGroup);
		jobTaskVo.setJobKey(jobKey);
		_log.debug(_LogPrefixStr + " JobTask 생성 :: jobKey=" + jobKey);

		// jobDetail 생성
		JobDetail job = generateJobDetail(jobKey, jobClass);

		// jobTaskVo 작업 초기화 세팅
		jobTaskVo.setJob(initJob(job, jobName, CollectConstants.INIT_RECCOUNT,
				CollectConstants.INIT_PREJOBSTATE));
		// JobDetail job = generateJobDetail(jobKey, (Class<? extends Job>)
		// ModuleJob.class); jobTaskVo.setJob(job);
		_log.debug(_LogPrefixStr + " \t\t jobDetail=" + job);

		// JobTriggerVO 생성
		JobTriggerVO jobTriggerVo = new JobTriggerVO(triggerName, triggerGroup,
				ScheduleStartTime, durationType, durationValue); // ScheduleStartTime[=HHmmss]
		_log.debug(_LogPrefixStr + " \t\t jobTriggerVo=" + jobTriggerVo);

		// Trigger 생성
		SimpleTrigger trigger = generateTrigger(jobTriggerVo);
		jobTaskVo.setTrigger(trigger);

		jobTaskVo.setRegistScheduleTime(DateUtil.now()); // 등록된 시간 세팅
		// jobTaskVo.setRegistScheduleTime(DateUtil.now()); // TODO::등록된 초기 스케줄
		// 시간 세팅

		return jobTaskVo;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobKey()
	 * 	Step0 ==> JobKey 획득 (jobName, jobGroup)
	 * <br>
	 * @param jobName
	 * @param jobGroup
	 * @return 
	 * type of JobKey
	 * </pre>
	 */
	public static JobKey generateJobKey(String jobName, String jobGroup) {
		JobKey jobKey = new JobKey(jobName, jobGroup);
		return jobKey;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobKey()
	 * 	Step0 ==> JobKey 획득 (JobVO)
	 * <br>
	 * @param jobVo
	 * @return 
	 * type of JobKey
	 * </pre>
	 */
	public static JobKey generateJobKey(JobVO jobVo) {
		JobKey jobKey = generateJobKey(jobVo.getJobName(), jobVo.getJobGroup());
		return jobKey;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobDetail()
	 * 	Step1 ==> JobDetail 획득 (jobKey, jobClass)
	 * <br>
	 * @param jobName
	 * @param jobGroup
	 * @param jobClass
	 * @return 
	 * type of JobDetail
	 * </pre>
	 */
	public static JobDetail generateJobDetail(String jobName, String jobGroup,
			Class<? extends Job> jobClass) {
		JobKey jobKey = generateJobKey(jobName, jobGroup);
		JobDetail job = generateJobDetail(jobKey, jobClass);
		return job;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobDetail()
	 * 	Step1 ==> JobDetail 획득 (jobKey, jobClass)
	 * <br>
	 * @param jobKey
	 * @param jobClass
	 * @return 
	 * type of JobDetail
	 * </pre>
	 */
	public static JobDetail generateJobDetail(JobKey jobKey,
			Class<? extends Job> jobClass) {
		// public static JobDetail generateJobDetail(String jobName, String
		// jobGroup, Class <? extends Job> jobClass) {

		JobDetail job = newJob(jobClass).withIdentity(jobKey).build();
		return job;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateJobDetail()
	 * 	Step1 ==> JobDetail 획득 (jobKey, jobClass)
	 * <br>
	 * @param jobVo
	 * @return 
	 * type of JobDetail
	 * </pre>
	 */
	public static JobDetail generateJobDetail(JobVO jobVo) {
		// public static JobDetail generateJobDetail(String jobName, String
		// jobGroup, Class <? extends Job> jobClass) {
		JobDetail job = null;
		if (jobVo != null && jobVo.getJobKey() != null)
			job = generateJobDetail(jobVo.getJobKey(), jobVo.getJobClass());
		else
			job = generateJobDetail(jobVo.getJobName(), jobVo.getJobGroup(),
					jobVo.getJobClass());
		return job;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateTrigger()
	 * 	- Step2 ==> trigger 획득 (triggerName, triggerGroup, ScheduleStartTime[=HHmmss])
	 *  - Usage : generateTrigger("trigger2", "group1", "034300", "SECOND", 10)
	 * <br>
	 * @param triggerName
	 * @param triggerGroup
	 * @param ScheduleStartTime
	 * @param durationType
	 * @param durationValue
	 * @return 
	 * type of SimpleTrigger
	 * </pre>
	 */
	public static SimpleTrigger generateTrigger(String triggerName,
			String triggerGroup, String ScheduleStartTime, String durationType,
			int durationValue) { // ScheduleStartTime[=HHmmss]

		Date startTime = ScheduleUtil.getScheduleRegistTime(ScheduleStartTime); // HHmmss
		ScheduleBuilder<SimpleTrigger> schedBuilder = ScheduleUtil
				.getScheduleBuilder(durationType, durationValue);

		SimpleTrigger trigger = newTrigger()
				.withIdentity(triggerName, triggerGroup).startAt(startTime)
				.withSchedule(schedBuilder)
				// .withRepeatCount(4))
				.build();

		return trigger;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.generateTrigger()
	 * 	- Step2 ==> trigger 획득 (triggerName, triggerGroup, ScheduleStartTime[=HHmmss])
	 * 	- generateTrigger("trigger2", "group1", "034300", "SECOND", 10)
	 * <br>
	 * @param jobTriggerVo
	 * @return 
	 * type of SimpleTrigger
	 * </pre>
	 */
	public static SimpleTrigger generateTrigger(JobTriggerVO jobTriggerVo) {
		SimpleTrigger trigger = generateTrigger(jobTriggerVo.getTriggerName(),
				jobTriggerVo.getTriggerGroup(),
				jobTriggerVo.getScheduleStartTime(),
				jobTriggerVo.getDurationType(), jobTriggerVo.getDurationValue());

		return trigger;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.initJob()
	 * 
	 * <br>
	 * 	return type of JobDetail
	 * <br>
	 * @param job
	 * @param jobIDs
	 * @param reccount
	 * @param prejobstate
	 * @return
	 * </pre>
	 */
	public static JobDetail initJob(JobDetail job, String jobIDs, int reccount,
			int prejobstate, JobStateVO jsVo, String msg) {
		JobDataMap dataMap = job.getJobDataMap();
		dataMap.put(CollectConstants.EXECUTION_JOBIDS, jobIDs); // 모듈 명
		dataMap.put(CollectConstants.EXECUTION_RECCOUNT, reccount); // 처리 레코드 수
		dataMap.put(CollectConstants.EXECUTION_PREJOBSTATE, prejobstate); // 처리
																			// 상태
		dataMap.put(CollectConstants.EXECUTION_JOBSTATEVO, jsVo);
		dataMap.put(CollectConstants.EXECUTION_MESSAGE, msg); // 메세지 명

		return job;
	}

	public static JobDetail initJob(JobDetail job, String jobIDs, int reccount,
			int prejobstate) {
		JobStateVO jsVo = new JobStateVO(jobIDs);

		return initJob(job, jobIDs, reccount, prejobstate, jsVo, "No-Message");
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.loadJobStateData()
	 * 
	 * <br>
	 * 	return type of JobStateInfoData
	 * <br>
	 * @return
	 * </pre>
	 */
	public static JobStateInfoData loadJobStateData(String pJobIDs) {
		JobStateInfoData jsid = new JobStateInfoData(pJobIDs);
		jsid.setPastJobStateVo(makeJobStateVO(pJobIDs));
		jsid.setCurrentJobStateVo(makeJobStateVO(pJobIDs));
		jsid.setNextJobStateVo(makeJobStateVO(pJobIDs));
		return jsid;
	}

	public static JobStateInfoData loadJobStateData(boolean type) {
		String pJobIDs = "";
		JobStateInfoData jsid = new JobStateInfoData(pJobIDs);
		if (type) { // useYN is true, only useYN is Y
			jsid.setPastJobStateVo(makeJobStateVO(pJobIDs));
			jsid.setCurrentJobStateVo(makeJobStateVO(pJobIDs));
			jsid.setNextJobStateVo(makeJobStateVO(pJobIDs));
		} else { // useYN is false or None, all useYN is Y or N
			jsid.setPastJobStateVo(makeJobStateVO(pJobIDs));
			jsid.setCurrentJobStateVo(makeJobStateVO(pJobIDs));
			jsid.setNextJobStateVo(makeJobStateVO(pJobIDs));
		}

		return jsid;
	}

	public static JobStateVO makeJobStateVO(String pJobIDs) {
		JobStateVO jsvo = new JobStateVO(pJobIDs);
		return jsvo;
	}

	/**
	 * <pre>
	 * Method : JobTaskUtil.getTjsVoMap()
	 * 	to get tjsVoMap
	 * <br> 
	 * @return the tjsVoMap : type of Map<String,JobStateVO>
	 * </pre>
	 */
	public static Map<String, JobStateVO> getTjsVoMap() {
		return tjsVoMap;
	}

	@SuppressWarnings("rawtypes")
	public static String makeModuleJobState(String type) {
		@SuppressWarnings("unused")
		String msg = "";
		String jobStateListStr = "";

		try {
			getModuleJobState(type);
			// System.out.println(""+getTjsVoMap().toString());
			String keyTaskName = "";
			JobStateVO jsVo = null;

			jobStateListStr += dispCurrentJobStateHeader();
			
			Iterator itr = getTjsVoMap().keySet().iterator();
			while (itr.hasNext()) {
				keyTaskName = (String) itr.next();
				jsVo = getTjsVoMap().get(keyTaskName);
				if ("PAST".equals(jsVo.getPoint())) {
					msg += "\t " + keyTaskName + " :: " + jsVo.toStringPast() + "\n";
					jobStateListStr += dispCurrentJobState(jsVo) + "\n";
				} else if ("CURRENT".equals(jsVo.getPoint())) {
					if (CollectConstants.CODE_JOB_STATE_DONE.equals(jsVo.getJobState())) {
						msg += "\t " + keyTaskName + " :: " + jsVo.toStringPast() + "\n";
						jobStateListStr += dispCurrentJobState(jsVo) + "\n";
					} else {
						msg += "\t " + keyTaskName + " :: " + jsVo.toStringCurrent() + "\n";
						jobStateListStr += dispNextJobState(jsVo) + "\n";
					}
				} else if ("NEXT".equals(jsVo.getPoint())) {
					msg += "\t " + keyTaskName + " :: " + jsVo.toStringNext() + "\n";
					jobStateListStr += dispNextJobState(jsVo) + "\n";
				}
			}
			jobStateListStr += "</tr></table>" + "\n";

			// System.out.println(jobStateListStr);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return jobStateListStr;
	}

	public static String dispCurrentJobState(JobStateVO jsVo) {
		String msg = "";
		String timeFormat = "yyyy-MM-dd HH:mm:ss";

		// Format :: NET_KEY_02 :: CURRENT :: JobStateVO [JobID=NET_KEY_02,
		// State=Done, Start=2012-09-27 14:38:05, End=2012-09-27 14:38:05,
		// From=2012-09-27 14:36:00, To=2012-09-27 14:38:00, Result=Succ, Total
		// Record=0, Total Time=0.0]
		msg += "</tr><tr>";
		msg += "<td>" + jsVo.getJobIDs() + "</td>";
		msg += "<td>" + jsVo.getJobState() + "</td>";
		msg += "<td>"
				+ DateUtil.dateToYmd(jsVo.getScheduleTime(), timeFormat)
				+ " ~ "
				+ DateUtil
						.dateToYmd(jsVo.getCompleteScheduleTime(), timeFormat)
				+ "</td>";
		msg += "<td>" + jsVo.getJobResult() + "</td>";
		msg += "<td>" + DateUtil.getFmtDateTime(jsVo.getJobCondStartTime(), 14)
				+ " ~ " + DateUtil.getFmtDateTime(jsVo.getJobCondEndTime(), 14)
				+ "</td>";
		msg += "<td>" + jsVo.getProcessTime() + jsVo.getTotalRecordCount()
				+ jsVo.getTotalFileCount() + "</td>";
		// msg += "</tr>";
		// msg += "\n";

		return msg;
	}

	public static String dispNextJobState(JobStateVO jsVo) {
		String msg = "";
		String timeFormat = "yyyy-MM-dd HH:mm:ss";

		// Format :: NET_KEY_02 :: CURRENT :: JobStateVO [JobID=NET_KEY_02,
		// State=Done, Start=2012-09-27 14:38:05, End=2012-09-27 14:38:05,
		// From=2012-09-27 14:36:00, To=2012-09-27 14:38:00, Result=Succ, Total
		// Record=0, Total Time=0.0]
		msg += "</tr><tr>";
		msg += "<td>" + jsVo.getJobIDs() + "</td>";
		msg += "<td>" + jsVo.getJobState() + "</td>";
		msg += "<td>" + DateUtil.dateToYmd(jsVo.getScheduleTime(), timeFormat)
				+ " ~ " + "n/a" + "</td>";
		msg += "<td>" + "n/a" + "</td>";
		msg += "<td>" + DateUtil.getFmtDateTime(jsVo.getJobCondStartTime(), 14)
				+ " ~ " + DateUtil.getFmtDateTime(jsVo.getJobCondEndTime(), 14)
				+ "</td>";
		msg += "<td>" + "n/a" + "</td>";
		// msg += "</tr>";
		// msg += "\n";

		return msg;
	}

	public static String dispCurrentJobStateHeader() {
		String msg = "";

		// Format :: NET_KEY_02 :: CURRENT :: JobStateVO [JobID=NET_KEY_02,
		// State=Done, Start=2012-09-27 14:38:05, End=2012-09-27 14:38:05,
		// From=2012-09-27 14:36:00, To=2012-09-27 14:38:00, Result=Succ, Total
		// Record=0, Total Time=0.0]
		msg += "<table><tr>";
		msg += "<th>작업명</th>";
		msg += "<th>상태</th>";
		msg += "<th>실행 시각</th>";
		msg += "<th>처리 결과</th>";
		msg += "<th>처리 조건</th>";
		msg += "<th>처리 상세</th>";
		// msg += "</tr>";
		// msg += "</tr></table>";
		// msg += "\n";

		return msg;
	}

	@SuppressWarnings("unused")
	public static void main(String[] args) {
		String msg = makeModuleJobState("NET_KEY_02");
	}

}
